// -----------------------------------------------------------------
//                      Team D
//                      Members:
//                            Ian Bell
//                            Art Ordonez
//                            Stephen Rippon
//                            Jason Vance
//                            Brent Wilkerson
//                      CS 4280 TTH 11:30am
//                      Team Assignment Final
//                      Dr. Rague
//                      Due: 6 Dec 2012
//                      Version: 1.2
// -----------------------------------------------------------------
//		Given a base FPS code framework, our code contains at least
//		5 improvements. What we came up with is a game including
//		an eccentric Top Hat collector in a snowy valley with
//		murderous rampaging Zombie-Vampire-Snowmen!
// -----------------------------------------------------------------
// -----------------------------------------------------------------
//	Change Control Section
// -----------------------------------------------------------------
//		Team Member:  Stephen Rippon
//		Version: 0.0
//		Date:  15 Nov 2012
//		Initial phase 20 code put together on SVN,
//		created both VS2010 and VS2012 project files.
// -----------------------------------------------------------------
//		Team Member:  Jason Vance
//		Version: 0.1
//		Date:  15 Nov 2012
//		Added intial AI for the SOD, created some new AI behaviors.
//		Increased fog distance.
// -----------------------------------------------------------------
//		Team Member:  Ian Bell
//		Version: 0.15
//		Date:  23 Nov 2012
//		Hid mouse cursor, improved mouse movement code.
// -----------------------------------------------------------------
//		Team Member:  Stephen Rippon
//		Version: 0.16
//		Date:  23 Nov 2012
//		Changed winmain event handler loop to process all events.
// -----------------------------------------------------------------
//		Team Member:  Jason Vance
//		Version: 0.2
//		Date:  26 Nov 2012
//		Added "clouds" to the world. No related AI changes yet.
// -----------------------------------------------------------------
//		Team Member:  Ian Bell
//		Version: 0.22
//		Date:  27 Nov 2012
//		Changed controls to use WASD.
// -----------------------------------------------------------------
//		Team Member:  Art Ordonez
//		Version: 0.23
//		Date:  27 Nov 2012
//		Added inital radar class.
// -----------------------------------------------------------------
//		Team Member:  Jason Vance
//		Version: 0.25
//		Date:  27 Nov 2012
//		Updated AI to run to the nearest cloud
//		until a player gets close.
// -----------------------------------------------------------------
//		Team Member:  Jason Vance
//		Version: 0.30
//		Date:  29 Nov 2012
//		Updated clouds to look more like clouds. AI has been improved
//		so that they try to stay alive, but attack the player if it's
//		worth it. Player can now be killed.
// -----------------------------------------------------------------
//		Team Member:  Ian Bell
//		Version: 0.35
//		Date:  30 Nov 2012
//		Updated movement velocity and code to allow diagonal movement.
//		Added sound effects: snowball_splat, snowball_throw.
//		Added background music loop.
//		Added bite sound on death.
//		Removed initial explosion sound.
// -----------------------------------------------------------------
//		Team Member:  Art Ordonez
//		Version: 0.36
//		Date:  30 Nov 2012
//		Updated radar display code.
// -----------------------------------------------------------------
//		Team Member:  Brent Wilkerson
//		Version: 0.37
//		Date:  30 Nov 2012
//		Added pinetree, hat, snowman, and helicopter code and model files.
//		They're all currently untextured cubes.
// -----------------------------------------------------------------
//		Team Member:  Ian Bell
//		Version: 0.40
//		Date:  1 Dec 2012
//		Added more wav files to project.
//		Added a "hacky" audio attenuation for snowball splat and snow shuffle.
// -----------------------------------------------------------------
//		Team Member:  Art Ordonez
//		Version: 0.41
//		Date:  2 Dec 2012
//		Fixed bug with radar, added a crosshair and center point to it.
// -----------------------------------------------------------------
//		Team Member:  Brent Wilkerson
//		Version: 0.42
//		Date:  2 Dec 2012
//		Added an ogro-textured snowman model.
// -----------------------------------------------------------------
//		Team Member:  Stephen Rippon
//		Version: 0.50
//		Date:  3 Dec 2012
//		Major code cleanup and reogranization, especially optimizing header files.
//		Updated VS projects to utilize precompiled headers, major build time increase.
//		Edited background music loop to loop more properly.
//		Fixed all warnings from base FPS code.
//		Brent's codefiles for his models integrated and fixed to compile properly.
//		Mouse sensitivity issues fixed.
// -----------------------------------------------------------------
//		Team Member:  Ian Bell
//		Version: 0.53
//		Date:  3 Dec 2012
//		Added moans and groans sound effects for the sod.
//		Altered attenuation distances, Altered movement code.
// -----------------------------------------------------------------
//		Team Member:  Art Ordonez
//		Version: 0.54
//		Date:  4 Dec 2012
//		Updated Radar class to no longer rely on CPolygon class.
// -----------------------------------------------------------------
//		Team Member:  Ian Bell
//		Version: 0.56
//		Date:  4 Dec 2012
//		Fixed repeating shuffle sound when sod dies.
//		Fixed initial movement bug, and some other random issues.
//		Added more Sods for testing purposes, clock now ticks upwards.
// -----------------------------------------------------------------
//		Team Member:  Brent Wilkerson
//		Version: 0.57
//		Date:  4 Dec 2012
//		Updated models and tied them to textures. Still need to
//		create the correct textures.
// -----------------------------------------------------------------
//		Team Member:  Stephen Rippon
//		Version: 0.58
//		Date:  4 Dec 2012
//		Changed ground texture to be snowy, made terrain larger.
// -----------------------------------------------------------------
//		Team Member:  Ian Bell
//		Version: 0.65
//		Date:  5 Dec 2012
//		Added hat objects (uses ogro model currently), collision logic
//		sound effect, and a counter for the hats.
//		Added laser beam and laser impact cues.
//		Adjusted attenuation range for rocket (snowball) impact.
//		Changed opening and closing messages.
//		Added sound effects for light beam fire and light beam collision.
// -----------------------------------------------------------------
//		Team Member:  Brent Wilkerson
//		Version: 0.70
//		Date:  5 Dec 2012
//		Added Snowman, hat, helicopter, and pinetree textures
// -----------------------------------------------------------------
//		Team Member:  Stephen Rippon
//		Version: 0.80
//		Date:  5 Dec 2012
//		Changed rocket weapon to snowball, using a gluSphere instead of the rocket model.
//		Added gravity to snowballs
//		Added a "lightbeam" using the lightbeamdamager object.
//		Player stops moving when using lightbeam.
//		Fixed crosshair being offcenter by drawing it in 2D, instead of a GUI font
//		Removed the ogro completely
//		Merged CSod code into CSnowman, updated all references to CSod in the code.
//		Fixed 2D drawing color states (affected radar and crosshair)
//		Changed CSod/CSnowman object model to the model. It's tiny, deadly, and hard to see!
// -----------------------------------------------------------------
//		Team Member:  Jason Vance
//		Version: 0.90
//		Date:  5 Dec 2012
//		Implemented hit system for enemies. Snowballs heal, light and sun hurts.
//		Enemy size is dependant on their hit points.
//		Fixed odd break-dancing behavior of AI enemies.
//		Stopped cloud particle system animations, increased size of particles.
//		Hats are generated when snowmen die, but they can't be seen.
// -----------------------------------------------------------------
//		Team Member:  Art Ordonez
//		Version: 0.91
//		Date:  5 Dec 2012
//		Updated radar, now draws points where the snowmen are initially generated.
// -----------------------------------------------------------------
//		Team Member:  Brent Wilkerson
//		Version: 0.92
//		Date:  6 Dec 2012
//		Added onDraw to the hat object.
//		Fixed hat rotation.
// -----------------------------------------------------------------
//		Team Member:  Art Ordonez
//		Version: 0.93
//		Date:  6 Dec 2012
//		Radar markers move now
// -----------------------------------------------------------------
//		Team Member:  Jason Vance
//		Version: 0.95
//		Date:  6 Dec 2012
//		Fixed snowman facing the wrong direction.
// -----------------------------------------------------------------
//		Team Member:  Stephen Rippon
//		Version: 1.0
//		Date:  6 Dec 2012
//		Worked with Art to get the radar working and properly
//		following the snowman objects.
// -----------------------------------------------------------------
//		Team Member:  Jason Vance
//		Version: 1.2
//		Date:  6 Dec 2012
//		Added helicopter and game logic to the game world. You win when 'h'
//		is pressed near the helecopter.
//		Fixed occasional crash where GetClosestCloud was rarely returning a NULL.
// -----------------------------------------------------------------
//		Team Member:  Ian Bell
//		Version: 1.3
//		Date:  6 Dec 2012
//		Added "Get to tha choppa!" sound effect
//		Added helicopter sounds and attenuation.
//		Created and updated the Narrative Document
// -----------------------------------------------------------------
//		Team Member:  Stephen Rippon
//		Version: 1.5
//		Date:  6 Dec 2012
//		Improved the radar to properly iterate through objects (fixes all related crashes)
//		Improved radar to show hat and helicopter objects, rotates objects based on camera's yaw value.
//		Made a few changes to gameplay-- snowmen melt slower, regenerate health slower when in AI_UNCARING and now in AI_ALERT.
//		Fixed the snowmen floating in the air, especially when their size shrinks.
//		Hats are now closer to the ground.
//		Changed size of helicopter and hat models to be more accurate.
//		Added massive changelog, the one you're reading right now!

// -----------------------------------------------------------------
#define WIN32_LEAN_AND_MEAN
/* Headers *******************************************************************************************************/

#include "OGLWindow.h"
#include "HiResTimer.h"

using namespace std;

bool exiting = false;
long windowWidth = 800;
long windowHeight = 600;
long windowBits = 32;
bool fullscreen = false;
HDC hDC;

OGLWindow * g_glRender = NULL;


void SetupPixelFormat(HDC hDC)
{
	int pixelFormat;

	PIXELFORMATDESCRIPTOR pfd =
	{
		sizeof(PIXELFORMATDESCRIPTOR),	// size
			1,							// version
			PFD_SUPPORT_OPENGL |		// OpenGL window
			PFD_DRAW_TO_WINDOW |		// render to window
			PFD_DOUBLEBUFFER,			// support double-buffering
			PFD_TYPE_RGBA,				// color type
			32,							// prefered color depth
			0, 0, 0, 0, 0, 0,			// color bits (ignored)
			0,							// no alpha buffer
			0,							// alpha bits (ignored)
			0,							// no accumulation buffer
			0, 0, 0, 0,					// accum bits (ignored)
			16,							// depth buffer
			0,							// no stencil buffer
			0,							// no auxiliary buffers
			PFD_MAIN_PLANE,				// main layer
			0,							// reserved
			0, 0, 0,					// no layer, visible, damage masks
	};

	pixelFormat = ChoosePixelFormat(hDC, &pfd);
	SetPixelFormat(hDC, pixelFormat, &pfd);
}

/* WndProc *******************************************************************************************************/
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	static HGLRC hRC;
	static HDC hDC;
	int height, width;
	int x, y;
	int fwKeys;
	LPARAM keyData;

	switch (msg)
	{
	case WM_CREATE:
		hDC = GetDC(hWnd);
		SetupPixelFormat(hDC);
		hRC = wglCreateContext(hDC);
		wglMakeCurrent(hDC, hRC);
		return 0;

	case WM_DESTROY:
	case WM_CLOSE:
	case WM_QUIT:
		wglMakeCurrent(hDC, NULL);
		wglDeleteContext(hRC);
		//PostQuitMessage(0);
		//Use the following instead of PostQuitMessage(0) which
		//does not work on Asus
		PostMessage(hWnd, WM_QUIT, 0, 0);
		return 0;

	case WM_SIZE:
		height = HIWORD(lParam);
		width = LOWORD(lParam);

		g_glRender->SetupProjection(width, height);
		return 0;

		// Ian Bell - 12/3/2012
	case WM_KEYUP:
		fwKeys = (int)wParam;
		keyData = lParam;

		g_glRender->OnKeyUp((int)wParam);
		break;

	case WM_KEYDOWN:
		fwKeys = (int)wParam;
		keyData = lParam;

		switch(fwKeys)
		{
		case VK_ESCAPE:
			wglMakeCurrent(hDC, NULL);
			wglDeleteContext(hRC);
			//PostQuitMessage(0);
			//Use the following instead of PostQuitMessage(0) which
			//does not work on Asus
			PostMessage(hWnd, WM_QUIT, 0, 0);
			break;
		default:
			g_glRender->OnKeyDown((int)wParam);
			break;
		}

		return 0;
	case WM_MOUSEMOVE:
		x = g_glRender->mouseX = g_glRender->GetMouseX(lParam);
		y = g_glRender->mouseY = g_glRender->GetMouseY(lParam);
		g_glRender->OnMouseMove(x, y);
		return 0;
	case WM_LBUTTONDOWN:		// left mouse button down
		g_glRender->OnMouseDownL(g_glRender->GetMouseX(lParam), g_glRender->GetMouseY(lParam));
		break;
	case WM_LBUTTONUP:			// left mouse button released
		g_glRender->OnMouseUpL(g_glRender->GetMouseX(lParam), g_glRender->GetMouseY(lParam));
		break;
	case WM_RBUTTONDOWN:			// left mouse button down
		g_glRender->OnMouseDownR(g_glRender->GetMouseX(lParam), g_glRender->GetMouseY(lParam));
		break;
	default:
		break;
	}
	return (DefWindowProc(hWnd, msg, wParam, lParam));
}

/* WinMain *******************************************************************************************************/
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevious, LPSTR lpCmdString, int CmdShow)
{

	WNDCLASSEX	wc;
	HWND		hwnd;
	MSG			msg;
	DWORD		dwExStyle;
	DWORD		dwStyle;
	RECT		windowRect;

	char str[700];

	g_glRender = new OGLWindow;

	windowRect.left=0L;
	windowRect.right=(long)windowWidth;
	windowRect.top=0L;
	windowRect.bottom=(long)windowHeight;

	wc.cbSize			= sizeof(WNDCLASSEX);
	wc.cbClsExtra		= 0;
	wc.cbWndExtra		= 0;
	wc.hbrBackground	= (HBRUSH)GetStockObject(WHITE_BRUSH);
	wc.hCursor			= LoadCursor (NULL, IDC_ARROW);
	wc.hIcon			= LoadIcon (NULL, IDI_APPLICATION);
	wc.hIconSm			= LoadIcon (NULL, IDI_WINLOGO);
	wc.hInstance		= hInstance;
	wc.lpfnWndProc		= WndProc;
	wc.lpszClassName	= "ShooterGame";
	wc.lpszMenuName		= NULL;
	wc.style			= CS_HREDRAW | CS_VREDRAW;
	if (!RegisterClassEx(&wc))
	{
		MessageBox (NULL,"Error: Cannot Register Class","ERROR!",MB_OK);
		return (0);
	}

	sprintf_s(str, sizeof(str), "You are an eccentric top hat collector. You've come to collect the enchanted top hats indigenous to this land. In order to get the top hats, you must first melt the zombie/vampire/snowmen that are given life by the top hats. Watch out! One bite and you're done for. Once you've collected your desired amount of top hats, you can call in a helicopter rescue. If you make it to the helicopter alive, you escape with both your booty intact and your booty intact. If not, then you are just another lost soul claimed by these frosty beasts.\n\n\n");
	strcat_s(str, sizeof(str), "Are you ready?");
	MessageBox(NULL, str, "The Valley of the Shadow of Death", MB_OK);

	sprintf_s(str, sizeof(str), "<w> - Forward\n<s> - Backward\n<a> - Left Strafe\n<d> - Right Strafe\n<h> - Call In Helicopter");
	strcat_s(str, sizeof(str), "\nRight mouse button throws snowballs. Snowballs slow down snowmen, but it increases their endurance.\nHold the left mouse button to fire a snowman/vampire melting light beam, but this is a stationary weapon.\nMove mouse to look around.\n\n");
	strcat_s(str, sizeof(str), "Numpad '+' - Increase mouse sensitivity\nNumpad '-' - Decrease mouse sensitivity\n\n");
	strcat_s(str, sizeof(str), "Developed for WSU CS4280 by:\nIan Bell\nArt Ordonez\nStephen Rippon\nJason Vance\nBrent Wilkerson\n");
		
	MessageBox(NULL, str, "Controls", MB_OK);
		
	if (MessageBox(NULL, "We are going to run in 800x600 mode, would you like to run in fullscreen?", "Fullscreen?", MB_YESNO) == IDYES)
		fullscreen = true;
	else
		fullscreen = false;



	if (fullscreen)										// fullscreen?
	{
		DEVMODE dmScreenSettings;						// device mode
		memset(&dmScreenSettings,0,sizeof(dmScreenSettings));
		dmScreenSettings.dmSize = sizeof(dmScreenSettings); 
		dmScreenSettings.dmPelsWidth = windowWidth;		// screen width
		dmScreenSettings.dmPelsHeight = windowHeight;	// screen height
		dmScreenSettings.dmBitsPerPel = windowBits;		// bits per pixel
		dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;

		if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
		{
			// setting display mode failed, switch to windowed
			MessageBox(NULL, "Display mode failed", NULL, MB_OK);
			fullscreen = FALSE; 
		}
	}

	if (fullscreen)								// Are We Still In Fullscreen Mode?
	{
		dwExStyle=WS_EX_APPWINDOW;				// Window Extended Style
		dwStyle=WS_POPUP;						// Windows Style
		ShowCursor(FALSE);						// Hide Mouse Pointer
	}
	else
	{
		dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;	// Window Extended Style
		dwStyle=WS_OVERLAPPEDWINDOW;					// Windows Style
	}

	AdjustWindowRectEx(&windowRect, dwStyle, FALSE, dwExStyle);     // Adjust Window To True Requested Size



	hwnd = CreateWindowEx(NULL, "ShooterGame", "Shooting Game Application", dwStyle,
							0, 0, 
							windowRect.right - windowRect.left, 
							windowRect.bottom - windowRect.top,
							NULL, NULL, hInstance, NULL);
	
	if (!hwnd) 
	{
		MessageBox (NULL,"Error: Failed to Create Window","ERROR!",MB_OK);
		return (0);
	}

	hDC = GetDC(hwnd);

	ShowWindow(hwnd, SW_SHOW);
	UpdateWindow(hwnd);
	CHiResTimer * timer = new CHiResTimer;
	timer->Init();

	ShowCursor(FALSE);

	g_glRender->Init();

	bool callExit = false;

	while (!callExit)
	{
		g_glRender->Prepare();
		g_glRender->Render(timer->GetElapsedSeconds(1));
		SwapBuffers(hDC);

		while (PeekMessage (&msg, hwnd, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage (&msg);
			if (msg.message == WM_QUIT) {
				callExit = true;
				break;
			}
		}
	}
	g_glRender->Shutdown();
	delete g_glRender;

	if (fullscreen)
	{
		ChangeDisplaySettings(NULL, 0);
		ShowCursor(TRUE);
	}

	return static_cast<int>(msg.wParam);
}